package com.jpro.module.system.api.user;

import cn.hutool.core.convert.Convert;
import com.fhs.core.trans.anno.AutoTrans;
import com.fhs.trans.service.AutoTransable;
import com.jpro.framework.common.pojo.CommonResult;
import com.jpro.framework.common.util.collection.CollectionUtils;
import com.jpro.module.system.api.user.dto.AdminUserRespDTO;
import com.jpro.module.system.api.user.dto.MemberCreateReqDTO;
import com.jpro.module.system.api.user.dto.MemberUserRespDTO;
import com.jpro.module.system.api.user.dto.UserAvatarDto;
import com.jpro.module.system.api.user.vo.*;
import com.jpro.module.system.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.jpro.module.system.api.user.AdminUserApi.PREFIX;

@FeignClient(name = ApiConstants.NAME) // TODO jprocms：fallbackFactory =
@Tag(name = "RPC 服务 - 管理员用户")
@AutoTrans(namespace = PREFIX, fields = {"nickname"})
public interface AdminUserApi extends AutoTransable<AdminUserRespDTO> {

    String PREFIX = ApiConstants.PREFIX + "/user";

    @GetMapping(PREFIX + "/get")
    @Operation(summary = "通过用户 ID 查询用户")
    @Parameter(name = "id", description = "用户编号", example = "1", required = true)
    CommonResult<AdminUserRespDTO> getUser(@RequestParam("id") Long id);

    @GetMapping(PREFIX + "/list-by-subordinate")
    @Operation(summary = "通过用户 ID 查询用户下属")
    @Parameter(name = "id", description = "用户编号", example = "1", required = true)
    CommonResult<List<AdminUserRespDTO>> getUserListBySubordinate(@RequestParam("id") Long id);

    @GetMapping(PREFIX + "/list")
    @Operation(summary = "通过用户 ID 查询用户们")
    @Parameter(name = "ids", description = "部门编号数组", example = "1,2", required = true)
    CommonResult<List<AdminUserRespDTO>> getUserList(@RequestParam("ids") Collection<Long> ids);

    @GetMapping(PREFIX + "/list-by-dept-id")
    @Operation(summary = "获得指定部门的用户数组")
    @Parameter(name = "deptIds", description = "部门编号数组", example = "1,2", required = true)
    CommonResult<List<AdminUserRespDTO>> getUserListByDeptIds(@RequestParam("deptIds") Collection<Long> deptIds);

    @GetMapping(PREFIX + "/list-by-post-id")
    @Operation(summary = "获得指定岗位的用户数组")
    @Parameter(name = "postIds", description = "岗位编号数组", example = "2,3", required = true)
    CommonResult<List<AdminUserRespDTO>> getUserListByPostIds(@RequestParam("postIds") Collection<Long> postIds);

    /**
     * 获得用户 Map
     *
     * @param ids 用户编号数组
     * @return 用户 Map
     */
    default Map<Long, AdminUserRespDTO> getUserMap(Collection<Long> ids) {
        List<AdminUserRespDTO> users = getUserList(ids).getCheckedData();
        return CollectionUtils.convertMap(users, AdminUserRespDTO::getId);
    }

    /**
     * 校验用户是否有效。如下情况，视为无效：
     * 1. 用户编号不存在
     * 2. 用户被禁用
     *
     * @param id 用户编号
     */
    default void validateUser(Long id) {
        validateUserList(Collections.singleton(id));
    }

    @GetMapping(PREFIX + "/valid")
    @Operation(summary = "校验用户们是否有效")
    @Parameter(name = "ids", description = "用户编号数组", example = "3,5", required = true)
    CommonResult<Boolean> validateUserList(@RequestParam("ids") Collection<Long> ids);

    @GetMapping("select")
    default List<AdminUserRespDTO> selectByIds(List<?> ids) {
        return getUserList(Convert.toList(Long.class, ids)).getCheckedData();
    }

    @GetMapping("select-list")
    default AdminUserRespDTO selectById(Object id) {
        return getUser(Convert.toLong(id)).getCheckedData();
    }

    @GetMapping(PREFIX + "/getMember")
    @Operation(summary = "通过用户 ID 查询用户")
    @Parameter(name = "id", description = "用户编号", example = "1", required = true)
    CommonResult<MemberUserRespDTO> getMember(@RequestParam("id") Long id);


    @PostMapping(PREFIX + "/update")
    @Operation(summary = "修改用户个人信息")
    CommonResult<Boolean> updateUserProfile(@Valid @RequestBody UserProfileUpdateReqVO reqVO);

    @PostMapping(PREFIX + "/update-password")
    @Operation(summary = "修改用户个人密码")
    CommonResult<Boolean> updateUserProfilePassword(@Valid @RequestBody UserProfileUpdatePasswordReqVO reqVO);

    @PostMapping(PREFIX + "/reset-password")
    @Operation(summary = "密码重置")
    CommonResult<Boolean> resetUserPassword(@Valid @RequestBody MemberResetPasswordReqVO reqVO);
    @RequestMapping(value = PREFIX + "/update-avatar", method = {RequestMethod.POST}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(summary = "上传用户个人头像")
    CommonResult<String> updateUserAvatar(@RequestPart("avatarFile") MultipartFile file) throws Exception;

    @PermitAll
    @PostMapping(value = PREFIX + "/update-avatar-url")
    @Operation(summary = "设置用户个人头像")
    CommonResult<String> updateUserAvatarUrl(@RequestBody UserAvatarDto avatarDto);

    @PermitAll
    @PostMapping(PREFIX + "/register")
    @Operation(summary = "注册会员")
    CommonResult<Long> registerMember(@Valid @RequestBody MemberCreateReqDTO reqDTO);

    @PermitAll
    @PostMapping(PREFIX + "/cmslogin")
    @Operation(summary = "使用账号密码登录")
    CommonResult<MemberUserRespVo> cmslogin(@RequestBody @Valid SimpleAuthLoginReqVO reqVO);

    @PermitAll
    @GetMapping(PREFIX + "/logout")
    @Operation(summary = "登出系统")
    CommonResult<Boolean> logout(@RequestParam("token") String token);

    @PermitAll
    @Operation(summary = "获取客户端SM2加密public key")
    @GetMapping(PREFIX + "/get-client-public-key")
    CommonResult<String> getClientPublicKey();

    @PermitAll
    @PostMapping(PREFIX + "/refresh-token")
    @Operation(summary = "刷新令牌")
    @Parameter(name = "refreshToken", description = "刷新令牌", required = true)
    CommonResult<MemberAuthLoginRespVO> refreshToken(@RequestParam("refreshToken") String refreshToken);

    @GetMapping(PREFIX + "/selectByUsername")
    @Operation(summary = "通过用户 用户名 查询用户")
    @Parameter(name = "username", description = "用户名", example = "username", required = true)
    CommonResult<AdminUserRespDTO> selectByUsername(@RequestParam("username") String username);

    @GetMapping(PREFIX + "/selectByMobile")
    @Operation(summary = "通过用户 用户名 查询用户")
    @Parameter(name = "mobile", description = "用户名", example = "mobile", required = true)
    CommonResult<AdminUserRespDTO> selectByMobile(@RequestParam("mobile") String mobile);

    @GetMapping(PREFIX + "/selectByEmail")
    @Operation(summary = "通过用户 用户名 查询用户")
    @Parameter(name = "email", description = "用户名", example = "email", required = true)
    CommonResult<AdminUserRespDTO> selectByEmail(@RequestParam("email") String email);

    @GetMapping(PREFIX + "/checkLongTimeNoLoginUser")
    @Operation(summary = "检查用户并锁定长期未登录用户")
    CommonResult<Boolean> checkLongTimeNoLoginUser();

    @PostMapping(PREFIX + "/lockUser")
    @Operation(summary = "锁定账户")
    CommonResult<Boolean> lockUser(@RequestBody @Valid UserLockReqVO reqVO);

}
